import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Like, Not, Repository } from 'typeorm';
import { Role } from './entities/role.entity';
import { CreateRoleDto } from './dto/create-role.dto';
import { UpdateRoleDto } from './dto/update-role.dto';
import { Permission } from '../user/entities/permission.entity';

@Injectable()
export class RoleService {
  @InjectRepository(Role)
  private roleRepository: Repository<Role>;

  @InjectRepository(Permission)
  private permissionRepository: Repository<Permission>;

  async create(createRoleDto: CreateRoleDto) {
    const { name, description } = createRoleDto;

    const existRole = await this.roleRepository.findOne({ where: { name } });

    if (existRole) {
      throw new HttpException('角色已存在', HttpStatus.BAD_REQUEST);
    }

    const role = new Role();
    role.name = name;
    role.description = description;

    try {
      await this.roleRepository.save(role);
      return '创建成功';
    } catch (e) {
      throw new HttpException('创建失败', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  async findAll(pageNum: number, pageSize: number, name?: string) {
    const skipCount = (pageNum - 1) * pageSize;

    const condition: Record<string, any> = {};
    if (name) {
      condition.name = Like(`%${name}%`);
    }

    const [roles, total] = await this.roleRepository.findAndCount({
      where: condition,
      skip: skipCount,
      take: pageSize,
      relations: ['permissions'],
    });

    return {
      roles,
      total,
    };
  }

  async findOne(id: number) {
    const role = await this.roleRepository.findOne({
      where: { id },
      relations: ['permissions'],
    });

    if (!role) {
      throw new HttpException('角色不存在', HttpStatus.BAD_REQUEST);
    }

    return role;
  }

  async update(id: number, updateRoleDto: UpdateRoleDto) {
    const { name, description } = updateRoleDto;

    const role = await this.roleRepository.findOne({ where: { id } });

    if (!role) {
      throw new HttpException('角色不存在', HttpStatus.BAD_REQUEST);
    }

    if (name) {
      const existRole = await this.roleRepository.findOne({
        where: { name, id: Not(id) },
      });

      if (existRole) {
        throw new HttpException('角色名已存在', HttpStatus.BAD_REQUEST);
      }

      role.name = name;
    }

    if (description) {
      role.description = description;
    }

    try {
      await this.roleRepository.save(role);
      return '更新成功';
    } catch (e) {
      throw new HttpException('更新失败', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  async remove(id: number) {
    const role = await this.roleRepository.findOne({
      where: { id },
      relations: ['users'],
    });

    if (!role) {
      throw new HttpException('角色不存在', HttpStatus.BAD_REQUEST);
    }

    if (role.users && role.users.length > 0) {
      throw new HttpException(
        '该角色下存在用户，无法删除',
        HttpStatus.BAD_REQUEST,
      );
    }

    try {
      await this.roleRepository.remove(role);
      return '删除成功';
    } catch (e) {
      throw new HttpException('删除失败', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  async updatePermissions(id: number, permissionIds: number[]) {
    const role = await this.roleRepository.findOne({ where: { id } });

    if (!role) {
      throw new HttpException('角色不存在', HttpStatus.BAD_REQUEST);
    }

    const permissions = await this.permissionRepository.findByIds(
      permissionIds,
    );

    role.permissions = permissions;

    try {
      await this.roleRepository.save(role);
      return '权限更新成功';
    } catch (e) {
      throw new HttpException('权限更新失败', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }
}
